home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 095 / tbbs105.arc / IO.INC < prev    next >
Text File  |  1985-05-09  |  19KB  |  741 lines

  1. var
  2.   cancelled : boolean;
  3.   inbuffer  : line;
  4.  
  5. function charin(withecho: boolean):char; forward;
  6.  
  7. procedure sendout(ch: char);
  8.  
  9. {Character output - bypasses word-wrap; also performs
  10.  "pause" and "abort" input character checks.}
  11.  
  12.   var temp: char;
  13.       tctl: boolean;
  14.  
  15.   begin
  16.     if not cancelled then begin
  17.       if inready then begin
  18.         temp := charin(noecho);
  19.         if (temp = pause) or (upcase(temp) = 'S') then begin
  20.           tctl := controls;
  21.           controls := true;
  22.           temp := charin(noecho);
  23.           controls := tctl;
  24.         end;
  25.         if (temp = abort) or (upcase(temp) = 'C') then cancelled := true;
  26.       end;
  27.       xmitchar(ch);
  28.       write(ch);
  29.       if printon then write(lst, ch);
  30.       if (ch = cr) and (lf = null) then writeln;
  31.     end;
  32.   end;
  33.  
  34. procedure flushbuff;
  35.  
  36.   var
  37.     outpointer: byte;
  38.  
  39.   begin
  40.     if length(buffer) > lastspace then
  41.       for outpointer := lastspace + 1 to length(buffer) do
  42.         sendout(buffer[outpointer]);
  43.     lastspace := length(buffer);
  44.   end;
  45.  
  46. procedure resetbuff;
  47.  
  48.   begin
  49.     bufpointer := 0;
  50.     lastspace := 0;
  51.     charcount := 0;
  52.     buffer := '';
  53.   end;
  54.  
  55. procedure charout(ch:char);
  56.  
  57. {Character output using word-wrap}
  58.  
  59.   var
  60.     buffull   : boolean;
  61.     temp      : long;
  62.  
  63.   begin
  64.     if caps then ch := upcase(ch);
  65.     if not (ch in [null..#31]) then charcount := succ(charcount);
  66.     if (ch = bs) and (charcount > 0) then charcount := charcount - 1;
  67.     buffer := buffer + ch;
  68.     bufpointer := length(buffer);
  69.     buffull := (charcount + 2 > width);
  70.     if buffull then begin
  71.       if (lastspace > 0)
  72.         then begin
  73.           buffer := copy(buffer, lastspace + 1, bufpointer - lastspace);
  74.           charcount := length(buffer);
  75.           lastspace := 0;
  76.           end {then}
  77.         else begin
  78.           flushbuff;
  79.           resetbuff;
  80.         end; {else}
  81.       sendout(cr);
  82.       sendout(lf);
  83.     end; {if}
  84.     if ch in [null..space] then flushbuff;
  85.     if (ch=cr) then resetbuff;
  86.   end;
  87.  
  88. procedure stringout(message:line);
  89.  
  90.   var
  91.     charpos: integer;
  92.  
  93.   begin
  94.     for charpos := 1 to length(message) do charout(message[charpos]);
  95.   end;
  96.  
  97. procedure lineout; (* "forward" declared in MACHDEP *)
  98.  
  99.   begin
  100.     stringout(message);
  101.     charout(cr);
  102.     charout(lf);
  103.   end;
  104.  
  105. function timedin: boolean;
  106.  
  107. {returns false if no character received in within
  108.  one second: used for XMODEM and input timeout.}
  109.  
  110.   var times: integer;
  111.  
  112.   begin
  113.     times := 0;
  114.     while (times < 500) and not inready do begin
  115.       times := times + 1;
  116.       delay(2);
  117.     end;
  118.     timedin := inready and cts;
  119.   end;
  120.  
  121. function charin;
  122.  
  123.   var
  124.     ch: char;
  125.     countime: integer;
  126.  
  127.   begin
  128.     ch := null;
  129.     countime := 0;
  130.     repeat
  131.       if timedin then ch := recvchar else countime := countime + 1;
  132.       if keypressed then read(kbd, ch);
  133.       if countime > 300 then hangup;
  134.       if not cts then ch := cr;
  135.       if (ch <> bs) and not controls then ch := chr(ord(ch) and 127);
  136.     until (ch in [abort, pause, bs, tab, cr, space..#127])
  137.       or (controls and (ch <> null));
  138.     if (ch = #127) and not controls then ch := bs;
  139.     if ch = #$8D then ch := cr;
  140.     if withecho then begin
  141.       sendout(ch);
  142.       if ch = bs then begin sendout(' '); sendout(bs); end;
  143.     end;
  144.     charin := ch;
  145.   end;
  146.  
  147. procedure flush;
  148.  
  149.   var
  150.     junk: char;
  151.  
  152.   begin
  153.     while inready do junk := charin(noecho);
  154.     clearstatus;
  155.   end;
  156.  
  157. function inputstring(withecho: boolean): line;
  158.  
  159.   var
  160.     temp:    line;
  161.     ch:      char;
  162.  
  163.   begin
  164.     temp := '';
  165.     flush;
  166.     repeat
  167.       ch := charin(noecho);
  168.       if (ch = bs) then begin
  169.         if length(temp) > 0 then begin
  170.           temp := copy(temp, 1, length(temp) - 1);
  171.           if withecho then begin
  172.             sendout(bs);
  173.             sendout(space);
  174.             sendout(bs);
  175.           end;
  176.         end;
  177.       end
  178.       else begin
  179.         if (ch <> cr) and (length(temp) < 80)
  180.         and ((ch in [tab, space..#126]) or controls) then begin
  181.           if ch = tab then repeat
  182.             temp := temp + space;
  183.             if withecho then sendout(space);
  184.           until (length(temp) mod 8) = 0
  185.           else begin
  186.             temp := temp + ch;
  187.             if withecho then sendout(ch);
  188.           end; {else}
  189.         end
  190.         else if (ch <> cr) then sendout(bell);
  191.       end;
  192.     until (ch = cr);
  193.     charout(cr); charout(lf);
  194.     inputstring := temp;
  195.   end;
  196.  
  197. function getinput(prompt:line; maxlength:integer; withecho:boolean):line;
  198.  
  199.   var posn: integer;
  200.       temp: char;
  201.  
  202.   begin
  203.     if cancelled then begin
  204.       cancelled := false;
  205.       lineout(space);
  206.     end;
  207.     if inbuffer = '' then begin
  208.       repeat
  209.         cancelled := false;
  210.         stringout(prompt);
  211.         if bl = bell then stringout(bl);
  212.       until cancelled = false;
  213.       inbuffer := inputstring(withecho);
  214.     end;
  215.     if maxlength = 1 then begin
  216.       if inbuffer = '' then temp := cr else begin
  217.         temp := inbuffer[1];
  218.         inbuffer := copy(inbuffer, 2, length(inbuffer)-1);
  219.         if (length(inbuffer) > 1) and (inbuffer[1] = ';')
  220.           then inbuffer := copy(inbuffer, 2, length(inbuffer)-1);
  221.       end; {else}
  222.       getinput := temp;
  223.     end
  224.     else begin
  225.       posn := pos(';', inbuffer);
  226.       if posn = 0 then posn := length(inbuffer) + 1;
  227.       if posn > maxlength then begin
  228.         posn := maxlength + 1;
  229.         inbuffer := copy(inbuffer, 1, maxlength);
  230.       end;
  231.       getinput := copy(inbuffer, 1, posn - 1);
  232.       if posn >= length(inbuffer)
  233.         then inbuffer := ''
  234.         else inbuffer := copy(inbuffer, posn + 1, length(inbuffer) - posn);
  235.     end;
  236.   end;
  237.  
  238. function allcaps(letters: person): person;
  239.  
  240.   var
  241.     loop: byte;
  242.     temp: person;
  243.  
  244.   begin
  245.     temp := '';
  246.     for loop := 1 to length(letters) do
  247.       temp := temp + upcase(letters[loop]);
  248.     allcaps := temp;
  249.   end;
  250.  
  251. procedure awaitcall;
  252.  
  253.   var
  254.     junk: char;
  255.  
  256.   begin
  257.     setbaud(fast);
  258.     writeln(cr + lf + 'Waiting for call...');
  259.     flush;
  260.     repeat
  261.       if keypressed then begin
  262.         read(kbd, junk);
  263.         local := junk = esc;
  264.         if local then setlocal else exitchar := junk;
  265.       end;
  266.     until cts or (exitchar = abort);
  267.     clrscr;
  268.     if exitchar <> abort then begin
  269.       if local then writeln('Local control.') else writeln('On line...');
  270.       delay(400);
  271.       flush;
  272.       junk := charin(noecho);
  273.       if badframe or (junk <> cr) then setbaud(slow);
  274.     end;
  275.   end;
  276.  
  277. procedure clearsc;
  278.  
  279.   begin
  280.     stringout(cs);
  281.     delay(500);   {allows time for slow terminal screen clears}
  282.   end;
  283.  
  284. function getcap(prompt: line): char;
  285.  
  286.   begin
  287.     getcap := upcase(getinput(prompt, 1, echo));
  288.   end;
  289.  
  290. function getint(nmax, star: integer; prompt: line): integer;
  291.  
  292.   var temp, test: integer;
  293.       outstr, userin: name;
  294.  
  295.   begin
  296.     str(nmax:4, outstr);
  297.     repeat
  298.       temp := 0;
  299.       userin := getinput(prompt, 4, echo);
  300.       val(userin, temp, test);
  301.       if (temp > nmax) then lineout('Number too large: ' + outstr + ' maximum.');
  302.     until ((test = 0) and (temp >= 0) and (temp <= nmax))
  303.      or (userin = '*') or (userin = '') or (userin = '?') or not cts;
  304.      if userin = '?' then getint := -1
  305.       else if userin = '*' then getint := star
  306.        else if test = 0 then getint := temp
  307.         else getint := 0;
  308.   end;
  309.  
  310. {Real-time clock support starts here...
  311.  these routines must remain, even if there's
  312.  no clock! To kill clock support, simply set
  313.  "clockin" in BBS.PAS to false.}
  314.  
  315. type monthname = string[3];
  316.      monames  = array[1..12] of monthname;
  317.  
  318. const months: monames = ('Jan','Feb','Mar','Apr','May','Jun',
  319.                          'Jul','Aug','Sep','Oct','Nov','Dec');
  320.  
  321. function time(month, date, hour, min, sec: byte): name;
  322.  
  323. {Returns 14-character string containing time and date}
  324.  
  325.   var
  326.     temps,
  327.     tempm,
  328.     tempd,
  329.     temph: string[2];
  330.  
  331.   begin
  332.     if clockin then begin
  333.       str(sec:2,temps);
  334.       str(min:2,tempm);
  335.       str(hour:2,temph);
  336.       str(date:2,tempd);
  337.       if sec < 10 then temps := '0' + temps[2];
  338.       if min < 10 then tempm := '0' + tempm[2];
  339.       if date < 10 then tempd := '0' + tempd[2];
  340.       time := temph + ':' + tempm + ':' + temps + ' ' + months[month] + tempd;
  341.     end
  342.     else time := '';
  343.   end;
  344.  
  345. procedure showtime;
  346.  
  347.   var
  348.     message: name;
  349.  
  350.   begin
  351.     if clockin then begin
  352.       clock(month, date, hour, min, sec);
  353.       message := time(month, date, hour, min, sec);
  354.       lineout('Time is: ' + message);
  355.     end;
  356.   end;
  357.  
  358. procedure calcconnect(var usehour, usemin, usesec: integer);
  359.  
  360.   begin
  361.     clock(month, date, hour, min, sec);
  362.     usemin := 0;
  363.     usehour := 0;
  364.     usesec := sec - onsec;
  365.     if usesec < 0 then begin
  366.       usesec := usesec + 60;
  367.       usemin := -1;
  368.     end;
  369.     usemin := min - onmin + usemin;
  370.     if usemin < 0 then begin
  371.       usemin := usemin + 60;
  372.       usehour := -1;
  373.     end;
  374.     usehour := hour - onhour + usehour;
  375.     if usehour < 0 then usehour := usehour + 24;
  376.   end;
  377.  
  378. procedure connecttime;
  379.  
  380.   var
  381.     message: name;
  382.  
  383.   begin
  384.     if clockin then begin
  385.       calcconnect(usehour, usemin, usesec);
  386.       message := copy(time(1, 1, usehour, usemin, usesec), 1, 8);
  387.       lineout('Connect time: ' + message);
  388.     end;
  389.   end;
  390.  
  391. procedure searchlib(infile: name; var result, libsects: integer);
  392.  
  393. {Library-file support adapted from DELIB.PAS
  394.  by Bela Lubkin of Borland International.}
  395.  
  396.   var
  397.     temp: name;
  398.     dirlength, offset, firstsec, loop, chrpos: integer;
  399.  
  400.   begin
  401.     firstsec := 0; libsects := 0;
  402.     blockread(libfile, libbuff, 1);
  403.     if libbuff[0] <> 0 then result := 1;
  404.     loop := 1;
  405.     while (result = 0) and (loop <= 11) do begin
  406.       if libbuff[loop] <> 32 then result := 1;
  407.       loop := loop + 1;
  408.     end;
  409.     result := result + libbuff[12] + libbuff[13];
  410.     if result = 0 then begin
  411.       dirlength := libbuff[14] + 256*libbuff[15];
  412.       if dirlength = 0 then result := 1;
  413.     end;
  414.     if result = 0 then begin
  415.       loop := 0;
  416.       while (loop < 4*dirlength-1) and (result = 0) and (firstsec = 0) do begin
  417.         loop := loop + 1;
  418.         offset := 32*(loop mod 4);
  419.         if offset = 0 then blockread(libfile, libbuff, 1);
  420.         if libbuff[offset] <> 0 then result := 1
  421.         else begin
  422.           temp := '';
  423.           for chrpos := 1 to 8 do
  424.             if libbuff[offset + chrpos] <> 32 then
  425.               temp := temp + chr(libbuff[offset + chrpos]);
  426.           if libbuff[offset + 9] <> 32 then begin
  427.             temp := temp + '.';
  428.             for chrpos := 9 to 11 do
  429.               if libbuff[offset + chrpos] <> 32 then
  430.                 temp := temp + chr(libbuff[offset + chrpos]);
  431.           end;
  432.           if cts and (infile = 'DIR') then lineout(temp);
  433.           if infile = temp then begin
  434.             firstsec := libbuff[offset+12] + 256*libbuff[offset+13];
  435.             libsects := libbuff[offset+14] + 256*libbuff[offset+15];
  436.             seek(libfile, firstsec);
  437.           end;
  438.         end;
  439.       end;
  440.       if infile = 'DIR' then result := 0;
  441.     end;
  442.   end;
  443.  
  444. procedure libassign(filename: longname; var result: integer);
  445.  
  446.   var
  447.     infile: name;
  448.     slash: integer;
  449.     library: boolean;
  450.  
  451.   begin
  452.     result := 0;
  453.     slash := pos('/', filename);
  454.     library := (slash > 0);
  455.     if library then begin
  456.       infile := copy(filename, slash + 1, length(filename) - slash);
  457.       filename := copy(filename, 1, slash - 1);
  458.       if pos('.', filename) = 0 then filename := filename + '.LBR';
  459.     end;
  460.     assign(libfile, filename);
  461.     {$I-} reset(libfile) {$I+};
  462.     result := IOresult;
  463.     if result = 0 then
  464.       if library then searchlib(infile, result, libsects)
  465.       else libsects := filesize(libfile);
  466.     libeof := (libsects = 0);
  467.   end;
  468.  
  469. procedure libblockread(var fileblock: filbuffer);
  470.  
  471.   begin
  472.     if libsects > 0 then blockread(libfile, fileblock, 1);
  473.     libsects := libsects - 1;
  474.     if libsects = 0 then libeof := true;
  475.   end;
  476.  
  477. procedure typefile(fname: longname; nowrap: boolean);
  478.  
  479. {Inline unsqueezer adapted from USQ.PAS V1.3, which
  480.  was written by Scott Loftesness, adapted for Turbo
  481.  Pascal by Steve Freeman and made compatible with
  482.  Non-Turbo Pascal squeezers by myself.- BM}
  483.  
  484.   const
  485.     recognize  = $FF76;
  486.     numvals    = 257;      { max tree size + 1 }
  487.     speof      = 256;      { special end of file marker }
  488.     dle: char  = #$90;
  489.  
  490.   type
  491.     tree       = array [0..255,0..1] of integer;
  492.  
  493.   var
  494.     in_ptr, result: integer;
  495.     in_buff: filbuffer;
  496.     dnode: tree;
  497.     inchar, curin, filecksum, bpos, i, repct, numnodes: integer;
  498.     c, lastchar: char;
  499.     origfile: name;
  500.     squeezed, eofin: boolean;
  501.  
  502.   function getc: integer;
  503.  
  504.     begin
  505.       in_ptr := in_ptr + 1;
  506.       if in_ptr > 127 then begin
  507.         if libeof then eofin := true
  508.         else begin
  509.           libblockread(in_buff);
  510.           in_ptr := 0;
  511.         end;
  512.       end;
  513.       if eofin then getc := 26 else getc := in_buff[in_ptr];
  514.     end;
  515.  
  516.   function getw: integer;
  517.  
  518.     var in1,in2: integer;
  519.  
  520.     begin
  521.       in1 := getc; in2 := getc;
  522.       getw := in1 + in2 shl 8;
  523.     end;
  524.  
  525.   procedure initialize;
  526.  
  527.     var str: string[14];
  528.  
  529.     begin
  530.       in_ptr := 127; squeezed := true;
  531.       repct:=0;   bpos:=99;   origfile:='';   eofin:=false;
  532.       i := getw;
  533.       if (recognize <> i) then begin
  534.         squeezed := false;
  535.         in_ptr := -1;
  536.       end
  537.       else begin
  538.         filecksum := getw;     { get checksum from chars 2 - 3 of file }
  539.         repeat    { build original file name }
  540.           inchar:=getc;
  541.           if inchar <> 0
  542.             then origfile := origfile + chr(inchar);
  543.         until inchar = 0;
  544.         lineout('Original file: ' + origfile);
  545.         numnodes:=ord(getw); { get the number of nodes in this files tree }
  546.         if (numnodes<0) or (numnodes>=numvals) then begin
  547.           squeezed := false;
  548.           in_ptr := -1;
  549.         end;
  550.       end;
  551.       if squeezed then begin
  552.         dnode[0,0]:= -(speof+1);
  553.         dnode[0,1]:= -(speof+1);
  554.         numnodes:=numnodes-1;
  555.         for i:=0 to numnodes do begin
  556.           dnode[i,0]:=getw;
  557.           dnode[i,1]:=getw;
  558.         end;
  559.       end;
  560.     end;
  561.  
  562.   function getuhuff: char;
  563.  
  564.     var i: integer;
  565.  
  566.     begin
  567.       i:=0;
  568.       repeat
  569.         bpos:=bpos+1;
  570.         if bpos>7 then begin
  571.           curin := getc;
  572.           bpos:=0;
  573.         end
  574.         else curin := curin shr 1;
  575.         i := ord(dnode[i,ord(curin and $0001)]);
  576.       until (i<0);
  577.       i := -(i+1);
  578.       if i=speof then begin
  579.         eofin:=true;
  580.         getuhuff:=chr(26);
  581.       end
  582.       else getuhuff:=chr(i);
  583.     end;
  584.  
  585.   function getcr: char;
  586.  
  587.     var c: char;
  588.  
  589.     begin
  590.       if squeezed then begin
  591.         if (repct>0) then begin
  592.           repct:=repct-1;
  593.           getcr:=lastchar;
  594.         end
  595.         else begin
  596.           c:=getuhuff;
  597.           if c<>dle then begin
  598.             getcr:=c;
  599.             lastchar:=c;
  600.           end
  601.           else begin
  602.             repct:=ord(getuhuff);
  603.             if repct=0 then getcr:=dle
  604.             else begin
  605.               repct:=repct-2;
  606.               getcr:=lastchar;
  607.             end;
  608.           end;
  609.         end;
  610.       end
  611.       else getcr := chr(getc);
  612.     end; {getcr}
  613.  
  614.   begin
  615.     libassign(fname, result);
  616.     if result <> 0 then lineout('Can''t find ' + fname + '!')
  617.     else begin
  618.       initialize;
  619.       while cts and not(cancelled or eofin) do begin
  620.         c:=getcr;
  621.         if c = #26 then eofin := true else begin
  622.           if nowrap then begin
  623.             if c <> #$8D then begin { <-- Allows no-wrap using WordStar files}
  624.               c := chr(ord(c) and 127);
  625.               if (c <> lnfd) then charout(c);
  626.               if c = cr then charout(lf);
  627.             end;
  628.           end else sendout(c);
  629.         end;
  630.       end;
  631.       close(libfile);
  632.     end;
  633.     unload;
  634.   end;
  635.  
  636. procedure outfile(fname: longname);
  637.  
  638.   begin
  639.     typefile(fname, true);
  640.   end;
  641.  
  642. function findid(caller: person): integer;
  643.  
  644.   var
  645.     usernum: integer;
  646.     index: integer;
  647.  
  648.   begin
  649.     usernum := 0;
  650.     index := 0;
  651.     lineout('Searching userlist...');
  652.     {$I-} reset(idfile) {$I+};
  653.     if IOresult <> 0 then rewrite(idfile);
  654.     while (usernum = 0) and not eof(idfile) do begin
  655.       index := index + 1;
  656.       read(idfile, idrec);
  657.       if idrec.user = caller then usernum := index;
  658.     end;
  659.     findid := usernum;
  660.   end;
  661.  
  662. procedure getcomments(maxline: integer);
  663.  
  664.   var
  665.     comfile: file of line;
  666.     linenum: integer;
  667.     head, temp: line;
  668.  
  669.   begin
  670.     str(maxline:1, temp);
  671.     lineout('Enter comment: up to ' + temp + ' lines, enter empty line to quit.');
  672.     lineout(space);
  673.     linenum := 0;
  674.     assign(comfile, 'COMMENTS.BBS');
  675.     {$I-} reset(comfile) {$I+};
  676.     if IOresult <> 0 then rewrite(comfile);
  677.     seek(comfile, filesize(comfile));
  678.     head := caller;
  679.     if clockin then head := head + '  ' + timeon;
  680.     repeat
  681.       linenum := linenum + 1;
  682.       str(linenum:2, temp);
  683.       stringout(temp + ': ');
  684.       temp := inputstring(echo);
  685.       if temp <> '' then begin
  686.         if linenum = 1 then write(comfile, head);
  687.         write(comfile, temp);
  688.       end;
  689.     until (temp = '') or (linenum = maxline) or not cts;
  690.     close(comfile);
  691.   end;
  692.  
  693. function nextuser: integer;
  694.  
  695.   var temp: integer;
  696.  
  697.   begin
  698.     stringout('Finding space for new user: ');
  699.     temp := findid('***');
  700.     if temp = 0 then nextuser := 1 + filesize(idfile) else nextuser := temp;
  701.   end;
  702.  
  703. procedure savedefaults;
  704.  
  705.   begin
  706.     if usernum = 0 then usernum := nextuser;
  707.     with idrec do begin
  708.       user := caller;
  709.       if expert then exfl := 0 else exfl := 255;
  710.       if clockin then lsto := timeon;
  711.       lstm := nextmess-1;
  712.       pass := password;
  713.       clr := cs;
  714.       acc := access;
  715.       bsp := bs;
  716.       lnf := lf;
  717.       upc := caps;
  718.       wid := width;
  719.     end;
  720.     seek(idfile, usernum - 1);
  721.     write(idfile, idrec);
  722.   end;
  723.  
  724. procedure disconnect;
  725.  
  726.   var
  727.     ch: char;
  728.  
  729.   begin
  730.     clearsc;
  731.     if not expert then lineout('Answering question with other than "Y" or "N" returns to BBS:');
  732.     ch := getcap('Do you want to leave comments to the Sysop (Y/N)? ');
  733.     if ch = 'Y' then getcomments(15);
  734.     if (ch = 'N') or (ch = 'Y') or not cts then begin
  735.       connecttime;
  736.       lineout('Thanks for calling, ' + caller);
  737.       savedefaults;
  738.       hangup;
  739.     end;
  740.   end;
  741.